amends "../snippetTest.pkl"

local str1 = "😀😈😍😎😡🤢🤣"
local str2 = "😍😎😡"

facts {
  ["isEmpty"] {
    !str1.isEmpty
  }

  ["isBlank"] {
    // all 25 Unicode characters with "White_Space" property
    "\u{0009}\u{000A}\u{000B}\u{000C}\u{000D}\u{0020}\u{0085}\u{00A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{2028}\u{2029}\u{202F}\u{205F}\u{3000}".isBlank
    !str1.isBlank
  }

  ["lastIndex"] {
    for (s in List(str1, str2)) {
      s.length == s.lastIndex + 1
    }
  }

  ["base64Decoded"] {
    str1.base64.base64Decoded == str1
    str2.base64.base64Decoded == str2
  }

  ["contains()"] {
    str1.contains(str2)
    str1.contains(str1)
    !str2.contains(str1)
    str1.contains(Regex("😍.+🤢"))
    !str1.contains(Regex("🤢.+😍"))
  }

  ["matches()"] {
    str1.matches(Regex("😀.+🤣"))
    str1.matches(Regex("😀😈😍😎😡🤢🤣"))
    !str1.matches(Regex("😀.+😎"))
  }

  ["startsWith()"] {
    str1.startsWith("😀😈😍")
    str1.startsWith(Regex("😀.+😍"))
    !str1.startsWith("😀😈x")
    !str1.startsWith(Regex("😍.+😀"))
  }

  ["endsWith()"] {
    str1.endsWith("😡🤢🤣")
    !str1.endsWith("😡🤢x")
  }

  ["isRegex"] {
    str1.isRegex
    #"😍*[😎😡]"#.isRegex
  }

  ["capitalize"] {
    str1.capitalize() == str1
    "ångström".capitalize() == "Ångström"
  }

  ["decapitalize"] {
    str1.decapitalize() == str1
    "Ångström".decapitalize() == "ångström"
  }
}

examples {
  ["length"] {
    str1.length
  }

  ["indexOf()"] {
    str1.indexOf("😍😎😡")
    module.catch(() -> str1.indexOf("😍😎x"))
    str1.indexOf(Regex("😍😎😡"))
    module.catch(() -> str1.indexOf(Regex(".?😎x")))
  }

  ["indexOfNull()"] {
    str1.indexOfOrNull("😍😎😡")
    str1.indexOfOrNull("😍😎x")
    str1.indexOfOrNull(Regex(".?😎😡"))
    str1.indexOfOrNull(Regex(".?😎x"))
  }

  ["reverse()"] {
    str1.reverse()
  }

  local str3 = "😀😈x😀😈y😀😈z"

  ["lastIndexOf()"] {
    str3.lastIndexOf("😀😈")
    module.catch(() -> str3.lastIndexOf("😍😎x"))
    str3.lastIndexOf(Regex("😀😈"))
    module.catch(() -> str3.lastIndexOf(Regex("😍😎x")))
  }

  ["lastIndexOfOrNull()"] {
    str3.lastIndexOfOrNull("😀😈")
    str3.lastIndexOfOrNull("😍😎x")
  }

  local str4 = "😀😀😈😈😍😍😀😀😈😈😍😍"

  ["split()"] {
    str4.split("😀😈")
    str4.split(Regex("[😀😈]"))
  }

  ["replaceAll()"] {
    str4.replaceAll("😀😀", "xx")
    str4.replaceAll(Regex("(😀+)😈"), "($0|$1)")
    module.catch(() -> str4.replaceAll(Regex("[😀😈]"), "$4; no such group"))
  }

  ["replaceFirst()"] {
    str4.replaceFirst("😀😀", "xx")
    str4.replaceFirst(Regex("(😀+)😈"), "($0|$1)")
    module.catch(() -> str4.replaceFirst(Regex("[😀😈]"), "$4; no such group"))
  }

  ["replaceLast()"] {
    str4.replaceLast("😀😀", "xx")
    str4.replaceLast(Regex("(😀+)😈"), "($0|$1)")
    module.catch(() -> str4.replaceLast(Regex("[😀😈]"), "$4; no such group"))
  }

  ["replaceAllMapped()"] {
    str4.replaceAllMapped("😀😀", (it) -> "├\(it)┤")
    str4.replaceAllMapped(Regex("(😀+)😈"), (it) -> "├\(it)┤")
  }

  ["replaceFirstMapped()"] {
    str4.replaceFirstMapped("😀😀", (it) -> "├\(it)┤")
    str4.replaceFirstMapped(Regex("(😀+)😈"), (it) -> "├\(it)┤")
  }

  ["replaceLastMapped()"] {
    str4.replaceLastMapped("😀😀", (it) -> "├\(it)┤")
    str4.replaceLastMapped(Regex("(😀+)😈"), (it) -> "├\(it)┤")
  }

  ["replaceRange()"] {
    str4.replaceRange(5, 10, "├┤")
    str4.replaceRange(10, 12, "extend beyond 😀 string end")
    module.catch(() -> str4.replaceRange(0, 100, "_😀_"))
    module.catch(() -> str4.replaceRange(-10, 5, "_😀_"))
  }


  ["toUpperCase()"] {
    "😀😈😍".toUpperCase()
  }

  ["toLowerCase()"] {
    "😀😈😍".toLowerCase()
  }

  local str5 = " \t 😀😈😍😎😡🤢🤣 \t \n"

  ["trim()"] {
    str5.trim()
  }

  ["trimStart()"] {
    str5.trimStart()
  }

  ["trimEnd()"] {
    str5.trimEnd()
  }

  ["chars"] {
    str1.chars
  }

  ["codePoints"] {
    str1.codePoints
  }

  ["toInt()"] {
    module.catch(() -> "😀😈😍".toInt())
  }

  ["toIntOrNull()"] {
    str1.toIntOrNull()
    str2.toIntOrNull()
    str3.toIntOrNull()
  }

  ["toFloat()"] {
    module.catch(() -> "😀😈😍".toFloat())
  }

  ["toFloatOrNull()"] {
    str1.toFloatOrNull()
    str2.toFloatOrNull()
    str3.toFloatOrNull()
  }

  ["take()"] {
    str1.take(0)
    str1.take(3)
    str1.take(42)
    module.catch(() -> str1.take(-1))
  }

  ["takeWhile()"] {
    str1.takeWhile((ch) -> true)
    str1.takeWhile((ch) -> false)
    str1.takeWhile((ch) -> ch <= "😍")
    module.catch(() -> str1.takeWhile((ch) -> 42))
  }

  ["takeLast()"] {
    str1.takeLast(0)
    str1.takeLast(3)
    str1.takeLast(42)
    module.catch(() -> str1.takeLast(-1))
  }

  ["takeLastWhile()"] {
    str1.takeLastWhile((ch) -> true)
    str1.takeLastWhile((ch) -> false)
    str1.takeLastWhile((ch) -> ch > "😍")
    module.catch(() -> str1.takeLastWhile((ch) -> 42))
  }

  ["drop()"] {
    str1.drop(0)
    str1.drop(3)
    str1.drop(42)
    module.catch(() -> str1.drop(-1))
  }

  ["dropWhile()"] {
    str1.dropWhile((ch) -> true)
    str1.dropWhile((ch) -> false)
    str1.dropWhile((ch) -> ch <= "😍")
    module.catch(() -> str1.dropWhile((ch) -> 42))
  }

  ["dropLast()"] {
    str1.dropLast(0)
    str1.dropLast(3)
    str1.dropLast(42)
    module.catch(() -> str1.dropLast(-1))
  }

  ["dropLastWhile()"] {
    str1.dropLastWhile((ch) -> true)
    str1.dropLastWhile((ch) -> false)
    str1.dropLastWhile((ch) -> ch > "😍")
    module.catch(() -> str1.dropLastWhile((ch) -> 42))
  }

  ["substring()"] {
    str1.substring(2, 2)
    str1.substring(2, 3)
    str1.substring(2, 4)
    str1.substring(0, 7)
    module.catch(() -> str1.substring(-1, 4))
    module.catch(() -> str1.substring(1, 8))
    module.catch(() -> str1.substring(3, 2))
  }

  ["substringOrNull()"] {
    str1.substringOrNull(2, 2)
    str1.substringOrNull(2, 3)
    str1.substringOrNull(2, 4)
    str1.substringOrNull(0, 7)
    str1.substringOrNull(-1, 4)
    str1.substringOrNull(1, 8)
    str1.substringOrNull(3, 2)
  }

  ["getOrNull()"] {
    str1.getOrNull(-1)
    str1.getOrNull(0)
    str1.getOrNull(3)
    str1.getOrNull(6)
    str1.getOrNull(7)
  }

  ["toBoolean()"] {
    module.catch(() -> "(😍😎😡".toBoolean())
  }

  ["toBooleanOrNull()"] {
    "(😍😎😡".toBooleanOrNull()
  }

  ["repeat()"] {
    str1.repeat(0)
    str1.repeat(1)
    str1.repeat(5)
  }

  ["sha1"] {
    str1.sha1
    str2.sha1
  }
  
  ["sha256"] {
    str1.sha256
    str2.sha256
  }
  
  ["sha256Int"] {
    str1.sha256Int
    str2.sha256Int
  }

  ["md5"] {
    str1.md5
    str2.md5
  }
  
  ["base64"] {
    str1.base64
    str2.base64
  }
}
